<?php

namespace App\Models;

use App\Exceptions\ApiException;
use App\Jobs\HandleRebate;
use App\Services\Base\HelpService;
use App\Services\Pay\StarsPay;
use App\Services\QuotaServices;
use Dcat\Admin\Traits\HasDateTimeFormatter;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * This is the model class for table "user_deposits"
 *
 * @property string $id
 * @property string $order_sn 订单号
 * @property string $third_name 三方名称
 * @property string $uid 用户id
 * @property string $from_symbol 来源币
 * @property string $from_amount 来源数量
 * @property string $to_symbol 目标币
 * @property string $to_amount 目标数量
 * @property string $to_real_amount 实际充值
 * @property string $rate 汇率
 * @property string $user_account 账户号
 * @property string $user_name 账户名称
 * @property string $to_address 转出地址
 * @property string $status 状态 1提交 2成功 3失败
 * @property string $remark 备注
 * @property string $image 图片
 * @property string $executed_tx 执行哈希
 * @property string $executed_at 执行完成时间
 * @property string $created_at 创建时间
 * @property string $updated_at 更新时间
 */
class UserDeposit extends BaseModel
{
    use HasDateTimeFormatter;

    protected $table = 'user_deposits';
    protected $guarded = [];

    /**
     * @param $uid
     * @param $symbol
     * @return mixed
     */
    public static function amountTotal($uid, $symbol = ASSET_SYMBOL_DEFAULT)
    {
        return Cache::remember("amount:total:{$uid}", 3600, function () use ($uid, $symbol) {
            return self::query()->where('uid', $uid)
                ->where('status', DEPOSIT_SUCCESS)
                ->where('to_symbol', $symbol)
                ->sum('to_amount');
        });
    }


    public function deposit($data)
    {
        $commit = false;
        try {
            $from_amount = $data['amount'];

            /**
             * @var $userDepositMethod UserDepositMethod
             */
            $userDepositMethod = UserDepositMethod::getOne($data['method_id']);
            $method_params = json_decode($userDepositMethod->params, true);

            $from_symbol = $method_params['unit_symbol'] ?? ASSET_SYMBOL_DEFAULT;
            $to_address = $method_params['account'] ?? "[SYSTEM]";
            $user_account = $method_params['account'] ?? "";
            $user_name = $method_params['name'] ?? "";
            $jump = $method_params['jump'] ?? "0";
            $jump_currency = $method_params['jump_currency'] ?? null;
            $jump_product = $method_params['jump_product'] ?? null;

            $commit = true;
            DB::beginTransaction();
            $order_sn = g_guid_date_unique_no();
            $rate = QuotaServices::getUnitPrice($from_symbol);
            $to_amount = QuotaServices::toUSD($from_amount, $from_symbol);

            $pay_url = "";
            if ($jump == 1) {
                $service = new StarsPay();
                $res = $service->pay([
                    'order_sn' => $order_sn,
                    'order_amount' => $to_amount,

                    'fiat_currency' => $jump_currency,
                    'jump_product' => $jump_product,
                ]);
                if (!$res['code']) {
                    throw new ApiException("充值失败");
                }
                $pay_url = $res['url'];
                $this->third_name = "StarsPay";
            }

            $this->uid = $data['uid'];
            $this->order_sn = $order_sn;
            $this->from_symbol = $from_symbol;
            $this->from_amount = $from_amount;
            $this->to_symbol = "USD";
            $this->to_amount = $to_amount;
            $this->to_real_amount = $to_amount;
            $this->rate = $rate;
            $this->user_account = $user_account;
            $this->user_name = $user_name;
            $this->to_address = $to_address;
            $this->status = DEPOSIT_COMMIT;
            $this->remark = $data['remark'] ?? "";
            $this->image = $data['image'] ?? "";

            if (!$this->save()) {
                throw new ApiException("充值失败");
            }

            DB::commit();
            return ['pay_url' => $pay_url];

        } catch (\Exception $e) {
            if ($commit) {
                DB::rollBack();
            }
            if ($e->getCode() == DEFAULT_CODE) {
                throw new ApiException($e->getMessage());
            } else {
                HelpService::log($e);
                throw new ApiException("系统异常");
            }
        }
        return ['pay_url' => ""];

    }


    public function success($to_real_amount)
    {
        try {
            DB::beginTransaction();
            UserNotification::query()->create([
                'uid' => $this->uid,
                'type' => USER_NOTIFICATION_DEPOSIT_SUCCESS,
                'amount' => $to_real_amount,
            ]);

            $this->update(['status' => DEPOSIT_SUCCESS, 'to_real_amount' => $to_real_amount]);
            $user_asset = UserAsset::getContractAccount($this->uid);
            $user_asset->assetChange(
                $this->uid,
                ASSET_SYMBOL_DEFAULT,
                $to_real_amount,
                ASSET_DEPOSITS,
                $this->id
            );

            DB::commit();
            HandleRebate::dispatch(['type' => REBATE_DEPOSIT, 'id' => $this->id]);
            return true;

        } catch (\Exception $e) {
            HelpService::forceLog($e);
            DB::rollBack();
        }
        return false;
    }

    public function fail()
    {
        try {
            DB::beginTransaction();
            UserNotification::query()->create([
                'uid' => $this->uid,
                'type' => USER_NOTIFICATION_DEPOSIT_FAIL,
                'amount' => $this->to_amount,
            ]);

            $this->update(['status' => DEPOSIT_FAIL]);
            DB::commit();
            return true;

        } catch (\Exception $e) {
            HelpService::forceLog($e);
            DB::rollBack();
        }
        return false;
    }

    /**
     * @param $uid
     * @param $amount
     * @param $remark
     * @return mixed
     */
    public static function depositSYS($uid, $amount, $remark = "")
    {
        return DB::transaction(function () use ($uid, $amount, $remark) {
            /**
             * @var $model_deposit UserDeposit
             */
            $model_deposit = self::query()->create([
                "uid" => $uid,
                "from_symbol" => ASSET_SYMBOL_DEFAULT,
                "from_amount" => $amount,
                "to_symbol" => ASSET_SYMBOL_DEFAULT,
                "to_amount" => $amount,
                "rate" => "0",
                "user_account" => "SYSTEM",
                "user_name" => "SYSTEM",
                "to_address" => "[SYSTEM]",
                "status" => DEPOSIT_SUCCESS,
                "remark" => $remark,
                "method_id" => 1,
                "executed_at" => now(),
                "created_at" => now(),
            ]);

            $user_asset = UserAsset::getContractAccount($uid);
            $user_asset->assetChange(
                $uid,
                ASSET_SYMBOL_DEFAULT,
                $amount,
                ASSET_DEPOSITS_SYS,
                $model_deposit->id
            );

            UserNotification::query()->create([
                'uid' => $uid,
                'type' => USER_NOTIFICATION_DEPOSIT_SUCCESS,
                'amount' => $model_deposit->to_amount,
            ]);

            HandleRebate::dispatch(['type' => REBATE_DEPOSIT, 'id' => $model_deposit->id]);
            return true;
        });
    }

    /**
     * @param $data
     * @return bool
     */
    public static function storeCapture($data)
    {
        $model = self::query()->find($data['order_id']);
        if (!$model || $model->uid != $data['uid']) { // 记录、归属
            return false;
        }

        return $model->fill([
            "image" => $data['image'],
        ])->save();
    }


    public function history($params)
    {
        $result = self::list("*", ['uid' => $params['uid']], $params);
        foreach ($result['list'] as &$v) {

        }
        return $result;
    }


    public function detail($params)
    {
        /**
         * @var $user_deposit UserDeposit
         */
        $user_deposit = self::getOne($params['id']);

        if ($user_deposit->uid != $params['uid']) {
            throw new ApiException("用户异常");
        }


        $result['account'] = $user_deposit->user_account;
        $result['name'] = $user_deposit->user_name;
        $result['from_amount'] = $user_deposit->from_amount;
        $result['status'] = $user_deposit->status;
        $result['image'] = $user_deposit->image;

        return $result;

    }

    public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
    {
        return $this->belongsTo(User::class, 'uid', 'id');
    }

}
